EBAZ4205 开发板 进入NAND Flash中PetaLinux

最近花50块钱买了个EBAZ4205,还是非常超值的。没事干想折腾一下他这个Linux系统,然后在网上搜索文章。就搜到了下面这个。按着他这个试了试。

参考文章:https://blog.csdn.net/zhys2007/article/details/106175366/

但是这里面存在一些问题。有的地方我重写一下。

首先是NAND分区信息:

1
2
3
4
5
6
7
8
9
0x000000000000-0x000000300000 : "nand-fsbl-uboot"
0x000000300000-0x000000800000 : "nand-linux"
0x000000800000-0x000000820000 : "nand-device-tree"
0x000000820000-0x000001220000 : "nand-rootfs"
0x000001220000-0x000002220000 : "nand-jffs2"
0x000002220000-0x000002a20000 : "nand-bitstream"
0x000002a20000-0x000006a20000 : "nand-allrootfs"
0x000006a20000-0x000007e00000 : "nand-release"
0x000007e00000-0x000008000000 : "nand-reserve"

继续阅读

Openjudge 2019计算机学科夏令营上机考试 Hopscotch

http://bailian.openjudge.cn/xly2019/C/

本体无法提交测试。样例已通过,可能TLE。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
#include<iostream>
#include<cstdio>
#include<queue>
#include<string>
using namespace std;
struct queueData {
    int p;
    string s;
    queueData(int p,string s):p(p),s(s){}
};
void bfs(int src, int dst) {
    queue<queueData> q;
    q.push(queueData(src, ""));
    while (!q.empty()) {
        queueData cur = q.front();
        q.pop();
        if (cur.p == dst) {
            cout << cur.s.size() << "\n";
            cout << cur.s << "\n";
            return;
        }
        q.push(queueData(cur.p * 3, cur.s + "H"));
        q.push(queueData(cur.p / 2, cur.s + "O"));
    }
}
int main() {
    int n, m;
    while (cin >> n >> m) {
        if (n == 0 && m == 0)break;
        else bfs(n, m);
    }
}

Openjudge 打印月历

http://noi.openjudge.cn/ch0113/24/

描述
给定年月,打印当月的月历表。

输入
输入为一行两个整数,第一个整数是年份year(1900 ≤ year ≤ 2099),第二个整数是月份month(1 ≤ month ≤ 12),中间用单个空格隔开。

输出
输出为月历表。月历表第一行为星期表头,如下所示:
Sun Mon Tue Wed Thu Fri Sat
其余各行一次是当月各天的日期,从1日开始到31日(30日或28日)。
日期数字应于星期表头右对齐,即各位数与星期表头相应缩写的最后一个字母对齐。日期中间用空格分隔出空白。

样例输入

1
2006 5

样例输出

1
2
3
4
5
6
Sun Mon Tue Wed Thu Fri Sat
      1   2   3   4   5   6
  7   8   9  10  11  12  13
 14  15  16  17  18  19  20
 21  22  23  24  25  26  27
 28  29  30  31

提示
闰年判断方法:能被4整除但不能被100整除,或者能被400整除。
1900年1月1日是周一。
继续阅读

Zynq 高层次综合HLS 项目开发经历(4) Vivado IP Integrator

IP Integrator这一块比较难配置,网上的教程比较乱,而且也少有针对AXIS Stream IP核专门配置的教程。所以我尝试着手把手的把配置过程在博客里展现出来。
我使用的开发板是ALinx AX7020,FPGA芯片zynq-xc7z020clg400-2。有些配置与我的板子是高度相关的,如果使用的是其他开发板请参照开发板提供商给的教程或参考资料配置。
继续阅读

Zynq 高层次综合HLS 项目开发经历(3) 代码移植及Vivado HLS的使用

首先简介一下HLS的整套开发流程。详细流程可参考[1][2]。
1、设计C/C++代码以及C/C++的TestBench
2、C Simulation,验证软件代码是否正确
3、C Synthesis,将C/C++化为Verilog/VHDL
4、C/RTL Co-Simulation,将C的TestBench与生成的RTL一起进行Simulation
5、Export RTL,导出IP核
HLS的使用本身不是一个难点,我猜Vivado HLS本身就是一个Eclipse搭起来的IDE,所以只要对Eclipse上手就行。难点在于代码移植。
继续阅读

Zynq 高层次综合HLS 项目开发经历(2) LZ77 x86软件实现

LZ77的x86软件实现repo地址可参见[1]。

要想实现软件,肯定需要把LZ77的算法读懂。慢慢啃就是了。我查询的参考资料可参见[2]。我主要参考了其中的“短语字典的维护”、“压缩和解压缩数据”、“LZ77的接口定义”三部分。而实现与定义则完全由自己制定。
继续阅读

Zynq 高层次综合HLS 项目开发经历(1) 概要

今年寒假我有幸参加了Xilinx的Winter Camp,在Camp上,讲者对HLS整个开发流程做了简单的介绍。为了巩固同学们的学习,主办方特意要求我们在冬令营结束之后自己用HLS做一个项目。本着拿一个证书和提高一下自己知识水平的想法,我也自己给自己定一个选题参加了这个项目。

原本是想要开发一个MD5的硬件实现的,后来在Github上面搜了一下,发现已经有人开发过HLS的MD5算法了。不得已只能放弃。后来经Foobar院猴哥推荐LZ77压缩算法,我发现也比较合适。于是就决定在硬件上实现一个LZ77压缩算法。值得注意的是,LZ77压缩算法只是一个大概的实现模板,具体怎么实现可以根据开发者的想法任意指定规范。所以这个压缩算法中的所有规范都是我自己指定的。因此和其他的压缩软件是不通用的。

现在硬软件设计基本上都已经做得差不多了,这一路走来坑真的不少。所以我决定写一个系列来记录一下自己遇到的坑,也许会对后来的同学有帮助。如果我的文章或者代码中有什么错误,也欢迎在博客里评论、Github上开issue留言给我。

首先,大概说一下高层次综合HLS是个什么东西。通俗易懂的讲,HLS就是可以把C/C++语言转换为Verilog/VHDL/System C的一个处理过程/软件。这样对于软件开发者来说,能够比较轻松简单的开发硬件设计。当然,其中也有很多与全软件开发不完全相同的部分。这些都需要我们另行学习。
然后,简介Zynq的两大部分:PS (Processing System) 指处理系统,它是在FPGA上提前实现好的硬核ARM处理器。PL (Programming Logic) 指FPGA可编程逻辑部分,它就是真正可操纵的硬件部分。PS和PL两部分可以通过预先定义好的总线接口相互连接。

我的开发流程是这样的:先在x86体系结构的软件上实现LZ77压缩算法,经过测试通过之后,转而开始开发硬件部分。首先使用Vivado HLS软件,移植软件C代码到硬件C代码,使用Directive规定接口和优化,生成IP核;打开Vivado,使用其中的IP Integrator,将Zynq处理系统 (Zynq Processing System) 的IP核以及其他各配套IP核与HLS开发的IP核连接在一起。综合实现生成比特流,导出硬件描述文件和比特流(到此为止的代码运行在PL端);切换到Vivado SDK中进行开发,使用硬件描述文件创建Standalone软件项目,编写在PS端运行的程序以及PL与PS的交互。到这里整体的开发流程就算完毕了。

在后面的文章里,我会依次的认真介绍一下各个部分的开发流程。

LZ77硬件实现项目:https://github.com/bjrjk/HLS-LZ77
LZ77软件实现项目:https://github.com/bjrjk/LZ77-Demo
Xilinx HLS设计流程课程:https://github.com/xupgit/High-Level-Synthesis-Flow-on-Zynq-using-Vivado-HLS

CUDA上的自旋锁(SpinLock)实现问题

最近在研究CUDA。其中有一个需求是要对一段代码加锁。CUDA里只提供了现成的对单个变量进行操作的原子操作库[1],而没有提供对一段代码加锁的机制,于是我就想怎么改造一下这个原子库。

一开始自己写了一段代码,差不多是这个样子的[2]。

1
2
3
4
5
6
__device__ inline void lock(int* p_mutex ){
    while(atomicCAS(p_mutex, 0, 1) != 0); // compare and swap
}
__device__ inline void unlock(int* p_mutex ){
    atomicExch(p_mutex, 0);// exchange
}

调用了之后发现从加锁的循环里压根就跑不出来。自己想了半天死活也搞不懂。然后从StackOverFlow上查到资料。发现这个和CUDA的Warp有关[3]。每个Warp由32个线程组成,它们必须同时执行相同的指令。如果用上述代码实现自旋锁。假定Warp中有一个Thread获得了锁,需要向下执行才能够释放锁。但是其他Thread却没得到锁,因此整个Warp就不能向下执行,始终卡在while循环里形成死锁。这种死锁叫SIMD死锁(SIMD DeadLock)。

之后翻了一大堆文献和网站,里面成堆的人都是实现同上,没有一个能用的。最后翻到了这篇文章[4],解决了问题。整理出的自旋锁的模板如下:

继续阅读