在Ubunutu 14.04中安装JabRef 3.5 (安装openjdk 8)

我一直都使用JabRef作为我的文档管理软件,因为它是开源的,支持bibtex并和Latex无缝连接,支持各数据库的自动文章搜索和bibtex生成。配戴使用Git作为后台的版本控制,现在我用它管理我的所有电子书和期刊文献,并在多电脑多操作系统保持同步。

可是最近发现了一个很尴尬的问题。Jabef的最新版本需要openjdk 8才能运行,而我所使用的Linux电脑由于工作原因都运行的是Ubuntu 14.04 LTS,支持的openjdk最高版本是7。为了能安装并使用上JabRef 3.5,我最终把openjdk 8给安上了。

安装Jabref 3.5其实比较简单。首先是安装系统自有版本,如果从来没有安装过JabRef的话。

$ sudo apt-get install jabref

这样就会安装一个JabRef 2.10b,非常老的版本。不过我们需要的这个安装会建立所有的系统链接,这样就不用手动建立图标和运行脚本了。安装之后:

$ which jabref
/usr/bin/jabref
$ ls -l /usr/share/java/jabref.jar
lrwxrwxrwx 1 root root 24 Aug 4 22:36 /usr/share/java/jabref.jar -> ../jabref/JabRef-2.10b2.jar

可见JabRef被安装到了/uar/bin,但这其实是一个脚本,会自动检查Java和其他扩展包的路径然后运行jabref.jar,而jabref.jar是一个软连接,指向了JabRef-2.10b2.jar。其实这方便了我们安装JabRef 3.5。

$ cd /usr/share/jabref
$ sudo wget https://github.com/JabRef/jabref/releases/download/v3.5/JabRef-3.5.jar
$ sudo mv /usr/share/java/jabref.jar /usr/share/java/jabref.jar.old
$ sudo ln -s ../jabref/JabRef-3.5.jar /usr/share/java/jabref.jar

现在我们就把jabref.jar指向了新的JarbRef-3.5.jar。不过这时候JabRef并不能正常运行:

$ jabref
Exception in thread "main" java.lang.UnsupportedClassVersionError: net/sf/jabref/JabRefMain : Unsupported major.minor version 52.0
at java.lang.ClassLoader.defineClass1(Native Method)
at java.lang.ClassLoader.defineClass(ClassLoader.java:803)
at java.security.SecureClassLoader.defineClass(SecureClassLoader.java:142)
at java.net.URLClassLoader.defineClass(URLClassLoader.java:449)
at java.net.URLClassLoader.access$100(URLClassLoader.java:71)
at java.net.URLClassLoader$1.run(URLClassLoader.java:361)
at java.net.URLClassLoader$1.run(URLClassLoader.java:355)
at java.security.AccessController.doPrivileged(Native Method)
at java.net.URLClassLoader.findClass(URLClassLoader.java:354)
at java.lang.ClassLoader.loadClass(ClassLoader.java:425)
at sun.misc.Launcher$AppClassLoader.loadClass(Launcher.java:308)
at java.lang.ClassLoader.loadClass(ClassLoader.java:358)
at sun.launcher.LauncherHelper.checkAndLoadMain(LauncherHelper.java:482)

这里的Unsupported major.minor.version 52.0实际上就是说需要jdk 8。所以,我们需要给Ubuntu 14.04安装openjdk 8:

$ sudo add-apt-repository ppa:openjdk-r/ppa
$ sudo apt-get update
$ sudo apt-get install openjdk-8-jre openjdk-8-jre-headless

不过这个时候系统默认的java版本仍然是openjdk 7,我们需要改变系统的默认java版本才能默认使用openjdk8:

$ sudo update-alternatives --config java

出现提示符后,请选择openjdk8的选项,这样默认java版本就被改变。

$ java -versionopenjdk version "1.8.0_91"
OpenJDK Runtime Environment (build 1.8.0_91-8u91-b14-0ubuntu4~14.04-b14)
OpenJDK 64-Bit Server VM (build 25.91-b14, mixed mode)

但是很糟糕的是,JabRef仍然不能自动运行,因为JabRef使用/usr/lib/java-wrappers/jvm-list.sh这个脚本来寻找java的默认版本,为了能正确的找到默认版本,我们需要作如下的修改:

  __jvm_openjdk7="/usr/lib/jvm/java-7-openjdk-$__arch /usr/lib/jvm/java-7-openjdk"
+ __jvm_openjdk8="/usr/lib/jvm/java-8-openjdk-$__arch /usr/lib/jvm/java-8-openjdk"

  # And a few aliases
  __jvm_gcj="$__jvm_gcj2"
- __jvm_openjdk="$__jvm_openjdk7 $__jvm_openjdk6"
+ __jvm_openjdk="$__jvm_openjdk8 $__jvm_openjdk7 $__jvm_openjdk6"

现在,JabRef应该可以正常运行了。终于。

VCS SystemVerilog 排序错误

SystemVerilog对数组(Array)和队列(queue)支持内置的排序算法sort()和rsort(),其中sort()是从大到小排序,rsort()则是从小到大排序。参见IEEE Standard for SystemVerilog IEEE Std 1800™-2012 Section 7.12.2

内置的排序算法支持使用多个键值进行排序。比如说标准里给出的这个例子:

struct { byte red, green, blue; } c [512];  
c.sort with ( item.red ); // sort c using the red field only
c.sort( x ) with ( {x.blue, x.green} ); // sort by blue then green

其中最后一个排序则是利用了blue和green两个键值排序,当blue键相等时,使用green进一步排序。

在VCS中,如果使用sort()对一个队列排序,当被排队列很长(在几千个数据以上)时,发现多键值排序的结果是错误的。第一键值的确是从大到小,但是当第一键值相等时,第二键值却变成了从小到大排序。

经验证Cadence Incisvie就能正确排序相同的代码,说明VCS的确存在一个bug。现在还没能找到一个较干净的例子来暴露问题。所用的VCS版本是vcs G-2012.09

BitBucket对学校用户免费无限用户套餐

Git是当前最流行的版本控制软件之一。使用Git的用户大多知道并使用www.github.com来存放自己的工程。GitHub对普通用户完全免费,但是免费工程必须是开放的(所有人都能访问)。创建私有工程是需要付费的。

与GitHub相比,BitBucket应该是使用最多的免费私有工程服务网站。只要私有工程的用户数量小于5个用户,免费用户可以建立无数个私有工程。超过5个用户则需要付费。

最近我发现BitBucket对学校用户免费开放无限用户的私有工程。我自己已经成功申请。

具体可参考:

http://www.atlassian.com/software/views/bitbucket-academic-license.jsp

https://bitbucket.org/plans

Do you offer free community or academic subscriptions?

When you sign up with your academic email address, we will automatically convert your account to an unlimited academic plan. If your account doesn’t automatically get converted, you can apply to have your institution added.

清理SweetIM流氓插件

不知道是上了什么网站中招了,从昨天下午回家开始,只要电脑是开的并且连着网,我的AVast!防火墙就会不停的报告有程序正尝试向随机的email地址发送带有恶意代码的email。最过分的时候是每秒钟有多于51封的Email被发出。

奇怪的是,我用AVast!查毒并查不出任何问题。于是只能上网搜索。最后发现了www.bleepingcomputer.com这个神奇的网站。这个网站上有各种我从来都没有听说过的扫描和清理病毒\木马\黑客程序的软件。同时还提供一对一的木马清除指导。甚至还提供防黑客指导课程。

开始我还不太相信,应为网上有各种打着杀毒旗号实为木马的软件和网站。但一番研究和wiki的结果之后发现这个网站上的内容都是真的。不是为他们做广告,不过以后中了莫名其妙的木马,传统杀毒软件不工作的时候,可以试一试这个网站。

说回我中的这个流氓插件。它叫SweetIM,Sweet Pack的成员。它会随着不小心点了垃圾网页的广告而植入。它的害处是时不时的在使用浏览器时弹出其他的页面。同时它还会自动向其他人发送带木马的垃圾邮件。它的传播方式主要是在注册表里面插入预加载的网页链接,这样一旦开了浏览器,流氓程序就开始执行了。由于没有实体文件的存在,传统杀毒软件根本不起作用。

检测到它归功于Malwarebytes Anti-Malware,也是bleepingcomputer上的一个软件。它的报告终于告诉我说系统的注册表出现了异常。清除它也很容易。可以使用Malwarebytes Anti-Malware直接清除注册表项。不过我用的是RKill + AdwCleaner的组合。同样这两个软件也在网站上。具体操作参见http://www.bleepingcomputer.com/virus-removal/remove-sweetpacks-toolbar。网页上的解释太详细了。

感谢这帮无私帮助他人抵御黑客的黑客们。

cppRange 多维范围计算库

范围计算是电路综合中的一个常见问题。在计算一个多比特信号是否被完全赋值,或者是否存在多驱动的时候,都需要计算该信号的范围。比如说一个信号(sig)有8比特(Verilog HDL):

wire [7:0] sig;
assign sig[3:0] = 4'd5;
assign sig[6:3] = 4'd3;

对于sig的两次赋值就造成了对sig[3]的多驱(两个assign同时对其赋值)。同时,sig[7]没有驱动。

为了检查没有驱动的情况,可以判断[7:0] 是否等于 [3:0] 和 [6:3]的并集([3:0] | [6:3])。检查多驱,则可查看[3:0]和[6:3]的交集是否为空([3:0] & [6:3])。这似乎很简单。但是一旦信号的范围支持多维,就复杂很多。比如下面的例子:

wire [7:0][3:0] multi_sig;
assign multi_sig[0] = 4'd9;
assign multi_sig[7:2] = 24'd96;
assign multi_sig[1][2:0] = 3'd7;
assign multi_sig[4][0]=1'b1;

multi_sig[4][0]被驱动了两次,而multi_sig[1][3]没有驱动。为了判断驱动,需要计算 [0] | [7:2] | [1][2:0] | [4][0]。这种一维和两维的混合是非常难计算的。将信号的声明考虑在内,则可以规范化范围计算,从而计算 [0][3:0] | [7:2][3:0] | [1:1][2:0] | [4:4][0:0]。可是,这仍然是一个难题,比如说如何表示 [1:1][2:0] | [4:4][0:0]?

这种问题在硬件综合之外的其他环境中也可能出现,但是到现在好像还没有一个很好的解决方按,更别说开源库。

所以我自己写了一个简单的多维范围计算库(C++)[https://github.com/wsong83/cppRange]

这个库可以用来计算一维或多维范围表达式。现在支持功能如下:

========
一个范围可以表示为:

1比特:            [3:3] or [3]
一维:             [3:0]
多维:             [5:0][2:-1]

* 范围默认为[上边界:下边界]。如果上边界<下边界,该范围非法。
* 该库使用STL支持任何可以比较和加减的数据类型。支持负数范围。

========
支持的计算:

包含 (>)
    [7:0] > [3:2]                               真
    [7:0][4:0][3:-2] > [1:0][3][1:0]            真
    [5:3][2:0] > [5:1][2:0]                     假
    [5:3][2:0] > [5:1]                          假 (非法计算)
* 相判断的两个多维范围必须有相同的维数,否则非法。

其他支持的比较 >=, <, <=, ==, !=

并集运算 (|)
    [7:3] | [4:0]                            -> [7:0]
    [5:4] | [1:0]                            -> []              // 空 (无法求值)
    [4:0][3:1] | [4:0][5:2]                  -> [4:0][5:1]
    [1:0][5:1] | [4:2][5:1]                  -> [4:0][5:1]
    [1:0][3:1] | [4:0][5:2]                  -> []              // 空 (非法运算)
    [1:0][3:1] | [4:0]                       -> []              // 空 (非法运算)
* 合并两个多维范围时,只能有一个纬度上的范围不等,同时该不等范围相邻才可计算。
交集运算 (&)
    [7:3] & [4:0]                            -> [4:3]
    [5:4] & [1:0]                            -> []
    [4:0][3:1] & [4:0][5:2]                  -> [4:0][3:2]
    [2:0][5:1] & [4:2][5:1]                  -> [2:2][5:1]
    [1:0][3:1] & [4:0][5:2]                  -> [1:0][3:2]
    [1:0][3:1] & [4:0]                       -> []
* 求取两个多维范围的交集时,两个范围必须有相同的维度。

去除 (-)
    [7:3] - [4:0]                            -> [7:5]
    [5:4] - [1:0]                            -> [5:4]
    [4:0][3:1] - [4:0][5:2]                  -> [4:0][1]
    [2:0][5:1] - [4:2][5:1]                  -> [1:0][5:1]
    [1:0][3:1] - [4:0][5:2]                  -> []
    [1:0][3:1] - [4:0]                       -> []
* 多维范围运算时,只能有一个维度上的范围不等。 

标准分割 (^)
    [7:3] ^ [4:0]                            -> [7:5],[4:3],[2:0]
    [5:4] ^ [1:0]                            -> []
    [4:0][3:1] ^ [4:0][5:2]                  -> [4:0][5:4],[4:0][3:2],[4:0][1:1]
    [2:0][5:1] ^ [4:2][5:1]                  -> [4:2][5:1],[2:2][5:1],[1:0][5:1]
    [1:0][3:1] ^ [4:0][5:2]                  -> []
    [1:0][3:1] ^ [4:0]                       -> []
* A ^ B = {High, A&B, Low}
* 多维范围运算时,只能有一个维度上的范围不等。同时范围相邻才可计算。

详细的使用则只能查看具体的代码了。

我计划在不久的将来扩展该库的运算,让其支持多维运算时多个维度上的不等范围。不过该计算的计算复杂度和时间则会大幅增长。

使用GitHub创建免费页面

建立免费页面已经不再是一件困难的事情,很多网站都提供类似的服务。比如说可以用google site和weebly创建免费网站。不过这些免费的网站往往不允许用户直接控制页面的源代码。他们的理念基本是帮助用户迅速并傻瓜的构造网页。如果需要从代码的级别搭建网站,往往需要购买服务器。

GitHub是Git版本控制的主要免费工程托管网站。用户可以基本没有限制的搭建免费的Git开源工程。多年以前Git就为每一个工程提供一个网页的branch,名字固定为gh-pages。用户可以上传一个静态网站到该branch,然后GitHub就将该branch以二级域名的方式公布。

比如说一个工程叫proj,由andrew创建。上传gh-pages这个branch之后,该网站就可以在
andrew.github.io/proj
访问到。

最近,Github将该功能拓展到个人网站。如果Andrew在自己的GitHub里面建立一个名为
andrew.github.io
的工程,并上传一个网站,那么该网站就可以用
andrew.github.io
访问。

和其他免费页面不同的是,GitHub允许用户创建所有由HTML, CCS和JS创建的静态页面。用户对页面有完全的控制权。同时,可以用git的方式对网页进行更新。感觉很有意思。(有机会自己做网页的自动化生成和更新了)

顺带,这意味着GitHub还免费提供了一个1G大小的免费网上文件夹。所有放到这个工程的文件可以被所有人公开获取。GitHub好像也没有被中国政府墙掉。比用Dropbox更有诱惑力。

我正打算将自己在weebly的页面搬到GitHub来。有时间学一下markdown和markup语言。

GitHub的解释:https://pages.github.com/

A C++ SAIF parser

SAIF is short for “switching activity interchange format”, which is a universal file format to record the signal switching activities in VLSI circuits. Both Synopsys and Cadence tools use this file format to save the signal switching results from simulations.

Recently due to the need of my own project, I need to extract switching information from SAIF files generated by commercial simulation tools. Due to the lack of an opensourced parser, I have written my own. It seems to work.

The parser can be accessed from https://github.com/wsong83/cppSaif

It reads a SAIF file and store the switching information into a C++ class called SaifDB, which is a C++ representation of the abstract syntax tree.

For the details of this parser, see the saif_db.hpp file.