blifutils 0.0.1

Sign up to get free protection for your applications and to get access to all the features.
@@ -0,0 +1,351 @@
1
+ /* Copyright (C) 2017 Théotime bollengier <theotime.bollengier@gmail.com>
2
+ *
3
+ * This program is free software: you can redistribute it and/or modify
4
+ * it under the terms of the GNU General Public License as published by
5
+ * the Free Software Foundation, either version 3 of the License, or
6
+ * (at your option) any later version.
7
+ *
8
+ * This program is distributed in the hope that it will be useful,
9
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
10
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11
+ * GNU General Public License for more details.
12
+ *
13
+ * You should have received a copy of the GNU General Public License
14
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
15
+ */
16
+
17
+
18
+ /* This file is an implementation of the ZPU processor (https://github.com/zylin/zpu)
19
+ * in the Piccolo minimalist hardware description language (https://github.com/TheotimeBollengier/piccolo).
20
+ */
21
+
22
+
23
+ module zpu_mem16(output CYC_O, // Wishbone interface
24
+ output STB_O,
25
+ output WE_O,
26
+ output<14> ADR_O,
27
+ output<32> DAT_O,
28
+ input<32> DAT_I,
29
+ input ACK_I,
30
+ output BREAKPOINT) :
31
+ /* ZPU registers */
32
+ reg<8> IR,
33
+ reg<16> PC := 'd0,
34
+ reg<14> SP := 'x2000, // stack pointer is initialized at 32k
35
+ reg IDIM := 'b0,
36
+ reg<32> REGA,
37
+ reg<32> REGB,
38
+ /* Instruction flags */
39
+ wire IM_I,
40
+ wire STORESP_I,
41
+ wire LOADSP_I,
42
+ wire ADDSP_I,
43
+ wire EMULATE_I,
44
+ wire POPPC_I,
45
+ wire LOAD_I,
46
+ wire STORE_I,
47
+ wire PUSHSP_I,
48
+ wire POPSP_I,
49
+ wire ADD_I,
50
+ wire AND_I,
51
+ wire OR_I,
52
+ wire NOT_I,
53
+ wire FLIP_I,
54
+ wire NOP_I,
55
+ /* State */
56
+ reg<4> state_ZPU := 'd0,
57
+ /* Others */
58
+ wire<14> SP_dec,
59
+ wire<14> SP_inc,
60
+ wire<16> PC_inc,
61
+ reg CYC_O_ := 'b0,
62
+ reg WE_O_ := 'b0,
63
+ reg<14> ADR_O_,
64
+ reg<32> DAT_O_,
65
+ reg BREAKPOINT_ := 'b0,
66
+ wire go_pop_a_start,
67
+ wire get_dati,
68
+ {
69
+ /* Decode instruction */
70
+ IM_I = IR[7];
71
+ STORESP_I = (IR[7:5] == 'b010);
72
+ LOADSP_I = (IR[7:5] == 'b011);
73
+ ADDSP_I = (IR[7:4] == 'b0001);
74
+ EMULATE_I = (IR[7:5] == 'b001);
75
+ POPPC_I = (IR == 'b00000100);
76
+ LOAD_I = (IR == 'b00001000);
77
+ STORE_I = (IR == 'b00001100);
78
+ PUSHSP_I = (IR == 'b00000010);
79
+ POPSP_I = (IR == 'b00001101);
80
+ ADD_I = (IR == 'b00000101);
81
+ AND_I = (IR == 'b00000110);
82
+ OR_I = (IR == 'b00000111);
83
+ NOT_I = (IR == 'b00001001);
84
+ FLIP_I = (IR == 'b00001010);
85
+ NOP_I = (IR == 'b00001011);
86
+
87
+
88
+ /* Get some usefull values */
89
+ SP_dec = SP - 'd1;
90
+ SP_inc = SP + 'd1;
91
+ PC_inc = PC + 'd1;
92
+
93
+ go_pop_a_start = STORESP_I | ADDSP_I | POPPC_I | LOAD_I | STORE_I | POPSP_I | ADD_I | AND_I | OR_I| NOT_I | FLIP_I;
94
+ get_dati = STORE_I | ADD_I | AND_I | OR_I;
95
+
96
+ /* ZPU FSM */
97
+ switch (state_ZPU) {
98
+ case 'd0: // FETCH_start_s
99
+ CYC_O_ = 'b1;
100
+ WE_O_ = 'b0;
101
+ ADR_O_ = PC[15:2];
102
+ state_ZPU = 'd1; // FETCH_end_s
103
+
104
+ case 'd1: // FETCH_end_s
105
+ if (ACK_I) {
106
+ CYC_O_ = 'b0;
107
+ PC = PC_inc;
108
+ switch (PC[1:0]) {
109
+ case 'b00:
110
+ IR = DAT_I[31:24];
111
+ case 'b01:
112
+ IR = DAT_I[23:16];
113
+ case 'b10:
114
+ IR = DAT_I[15:8];
115
+ case 'b11:
116
+ IR = DAT_I[7:0];
117
+ }
118
+ state_ZPU = 'd2; // DECODE_s
119
+ }
120
+
121
+ /* Decode */
122
+ case 'd2: // DECODE_s
123
+ if (go_pop_a_start) {
124
+ state_ZPU = 'd3; // POP_A_start_s
125
+ }
126
+ elsif (IM_I) {
127
+ if (!IDIM) {
128
+ if (IR[6]) {
129
+ REGA = 'b11111111111111111111111111 : IR[5:0];
130
+ } else {
131
+ REGA = 26b0 : IR[5:0];
132
+ }
133
+ state_ZPU = 'd14; // PUSH_start_s
134
+ } else {
135
+ REGA[6:0] = IR[6:0];
136
+ state_ZPU = 'd3; // POP_A_start_s
137
+ }
138
+ }
139
+ elsif (LOADSP_I) {
140
+ state_ZPU = 'd7; // LOAD_STACK_start_s
141
+ }
142
+ elsif (PUSHSP_I) {
143
+ REGA = 16b0 : SP : 2b0;
144
+ state_ZPU = 'd14; // PUSH_start_s
145
+ }
146
+ elsif (EMULATE_I) {
147
+ REGA = 16b0 : PC;
148
+ PC = 6b0 : IR[4:0] : 5b0;
149
+ state_ZPU = 'd14; // PUSH_start_s
150
+ }
151
+ elsif (NOP_I) {
152
+ state_ZPU = 'd0; // FETCH_start_s
153
+ } else {
154
+ state_ZPU = 'd15; // BREAKPOINT_s
155
+ }
156
+
157
+
158
+ /* Start POP first value */
159
+ case 'd3: // POP_A_start_s
160
+ CYC_O_ = 'b1;
161
+ WE_O_ = 'b0;
162
+ ADR_O_ = SP;
163
+ SP = SP_inc;
164
+ state_ZPU = 'd4; // POP_A_end_s
165
+
166
+
167
+ /* End POP first value */
168
+ case 'd4: // POP_A_end_s
169
+ if (ACK_I) {
170
+ CYC_O_ = 'b0;
171
+
172
+ if (get_dati) {
173
+ REGA = DAT_I;
174
+ state_ZPU = 'd5; // POP_B_start_s
175
+ }
176
+ elsif (IM_I) {
177
+ REGA[31:7] = DAT_I[24:0];
178
+ state_ZPU = 'd14; // PUSH_start_s
179
+ }
180
+ elsif (STORESP_I) {
181
+ REGA = DAT_I;
182
+ state_ZPU = 'd9; // STORE_STACK_start_s
183
+ }
184
+ elsif (ADDSP_I) {
185
+ REGA = DAT_I;
186
+ state_ZPU = 'd7; // LOAD_STACK_start_s
187
+ }
188
+ elsif (POPPC_I) {
189
+ PC = DAT_I[15:0];
190
+ state_ZPU = 'd0; // FETCH_start_s
191
+ }
192
+ elsif (LOAD_I) {
193
+ REGA = DAT_I;
194
+ state_ZPU = 'd11; // LOAD_MEM_start_s
195
+ }
196
+ elsif (POPSP_I) {
197
+ SP = DAT_I[15:2];
198
+ state_ZPU = 'd0; // FETCH_start_s
199
+ }
200
+ elsif (NOT_I) {
201
+ REGA = ~(DAT_I);
202
+ state_ZPU = 'd14; // PUSH_start_s
203
+ }
204
+ elsif (FLIP_I) {
205
+ REGA = DAT_I[0] : DAT_I[1] : DAT_I[2] : DAT_I[3] : DAT_I[4] : DAT_I[5] : DAT_I[6] : DAT_I[7] :
206
+ DAT_I[8] : DAT_I[9] : DAT_I[10] : DAT_I[11] : DAT_I[12] : DAT_I[13] : DAT_I[14] : DAT_I[15] :
207
+ DAT_I[16] : DAT_I[17] : DAT_I[18] : DAT_I[19] : DAT_I[20] : DAT_I[21] : DAT_I[22] : DAT_I[23] :
208
+ DAT_I[24] : DAT_I[25] : DAT_I[26] : DAT_I[27] : DAT_I[28] : DAT_I[29] : DAT_I[30] : DAT_I[31];
209
+ state_ZPU = 'd14; // PUSH_start_s
210
+ }
211
+ else {
212
+ state_ZPU = 'd15; // BREAKPOINT_s
213
+ }
214
+ }
215
+
216
+
217
+ /* Start POP second value */
218
+ case 'd5: // POP_B_start_s
219
+ CYC_O_ = 'b1;
220
+ WE_O_ = 'b0;
221
+ ADR_O_ = SP;
222
+ SP = SP_inc;
223
+ state_ZPU = 'd6; // POP_B_end_s
224
+
225
+
226
+ /* End POP second value */
227
+ case 'd6: // POP_B_end_s
228
+ if (ACK_I) {
229
+ CYC_O_ = 'b0;
230
+ if (STORE_I) {
231
+ REGB = DAT_I;
232
+ state_ZPU = 'd13; // STORE_MEM_start_s
233
+ }
234
+ elsif (ADD_I) {
235
+ REGA = REGA + DAT_I;
236
+ state_ZPU = 'd14; // PUSH_start_s
237
+ }
238
+ elsif (AND_I) {
239
+ REGA = REGA & DAT_I;
240
+ state_ZPU = 'd14; // PUSH_start_s
241
+ }
242
+ elsif (OR_I) {
243
+ REGA = REGA | DAT_I;
244
+ state_ZPU = 'd14; // PUSH_start_s
245
+ }
246
+ else {
247
+ state_ZPU = 'd15; // BREAKPOINT_s
248
+ }
249
+ }
250
+
251
+
252
+ /* Start LOAD from STACK */
253
+ case 'd7: // LOAD_STACK_start_s
254
+ CYC_O_ = 'b1;
255
+ WE_O_ = 'b0;
256
+ if (LOADSP_I) {
257
+ ADR_O_ = SP + (9b0 : (~IR[4]) : IR[3:0]);
258
+ }
259
+ elsif (ADDSP_I) {
260
+ ADR_O_ = SP + (10b0 : IR[3:0]) - 'd1;
261
+ }
262
+ state_ZPU = 'd8; // LOAD_STACK_end_s
263
+
264
+
265
+ /* End LOAD from STACK */
266
+ case 'd8: // LOAD_STACK_end_s
267
+ if (ACK_I) {
268
+ CYC_O_ = 'b0;
269
+ if (LOADSP_I) {
270
+ REGA = DAT_I;
271
+ }
272
+ elsif (ADDSP_I) {
273
+ REGA = REGA + DAT_I;
274
+ }
275
+ state_ZPU = 'd14; // PUSH_start_s
276
+ }
277
+
278
+
279
+ /* Start STORE to STACK */
280
+ case 'd9: // STORE_STACK_start_s
281
+ CYC_O_ = 'b1;
282
+ WE_O_ = 'b1;
283
+ ADR_O_ = SP + (9b0 : (~IR[4]) : IR[3:0]) - 'd1;
284
+ DAT_O_ = REGA;
285
+ state_ZPU = 'd10; // store_end_s
286
+
287
+
288
+ /* End STORE */
289
+ case 'd10: // store_end_s
290
+ if (ACK_I) {
291
+ CYC_O_ = 'b0;
292
+ state_ZPU = 'd0; // FETCH_start_s
293
+ }
294
+
295
+
296
+ /* Start LOAD from MEM */
297
+ case 'd11: // LOAD_MEM_start_s
298
+ CYC_O_ = 'b1;
299
+ WE_O_ = 'b0;
300
+ ADR_O_ = REGA[15:2];
301
+ state_ZPU = 'd12; // LOAD_MEM_end_s
302
+
303
+
304
+ /* End LOAD from MEM */
305
+ case 'd12: // LOAD_MEM_end_s
306
+ if (ACK_I) {
307
+ CYC_O_ = 'b0;
308
+ REGA = DAT_I;
309
+ state_ZPU = 'd14; // PUSH_start_s
310
+ }
311
+
312
+
313
+ /* Start STORE to MEM */
314
+ case 'd13: // STORE_MEM_start_s
315
+ CYC_O_ = 'b1;
316
+ WE_O_ = 'b1;
317
+ ADR_O_ = REGA[15:2];
318
+ DAT_O_ = REGB;
319
+ state_ZPU = 'd10; // store_end_s
320
+
321
+
322
+ /* Start PUSH */
323
+ case 'd14: // PUSH_start_s
324
+ CYC_O_ = 'b1;
325
+ WE_O_ = 'b1;
326
+ ADR_O_ = SP_dec;
327
+ DAT_O_ = REGA;
328
+ SP = SP_dec;
329
+ state_ZPU = 'd10; // store_end_s
330
+
331
+
332
+ /* BREAKPOINT state */
333
+ case 'd15: // BREAKPOINT_s
334
+ CYC_O_ = 'b0;
335
+ BREAKPOINT_ = 'b1;
336
+ }
337
+
338
+
339
+ /* IDIM Flag */
340
+ if (state_ZPU == 'd2) { // DECODE_s
341
+ IDIM = IM_I;
342
+ }
343
+
344
+ CYC_O = CYC_O_;
345
+ STB_O = CYC_O_;
346
+ WE_O = WE_O_;
347
+ ADR_O = ADR_O_;
348
+ DAT_O = DAT_O_;
349
+ BREAKPOINT = BREAKPOINT_;
350
+ }
351
+
@@ -0,0 +1,31 @@
1
+ ##
2
+ # Copyright (C) 2017 Théotime bollengier <theotime.bollengier@gmail.com>
3
+ #
4
+ # This file is part of Blifutils.
5
+ #
6
+ # Blifutils is free software: you can redistribute it and/or modify
7
+ # it under the terms of the GNU General Public License as published by
8
+ # the Free Software Foundation, either version 3 of the License, or
9
+ # (at your option) any later version.
10
+ #
11
+ # Blifutils is distributed in the hope that it will be useful,
12
+ # but WITHOUT ANY WARRANTY; without even the implied warranty of
13
+ # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14
+ # GNU General Public License for more details.
15
+ #
16
+ # You should have received a copy of the GNU General Public License
17
+ # along with Blifutils. If not, see <http://www.gnu.org/licenses/>.
18
+
19
+
20
+ module BlifUtils
21
+ VERSION = '0.0.1'
22
+ end
23
+
24
+ require 'blifutils/parser'
25
+ require 'blifutils/netlist'
26
+ require 'blifutils/elaborator'
27
+ require 'blifutils/layering'
28
+ require 'blifutils/level_analyzer'
29
+ require 'blifutils/simulator_generator'
30
+ require 'blifutils/blif_to_vhdl'
31
+
@@ -0,0 +1,185 @@
1
+ ##
2
+ # Copyright (C) 2017 Théotime bollengier <theotime.bollengier@gmail.com>
3
+ #
4
+ # This file is part of Blifutils.
5
+ #
6
+ # Blifutils is free software: you can redistribute it and/or modify
7
+ # it under the terms of the GNU General Public License as published by
8
+ # the Free Software Foundation, either version 3 of the License, or
9
+ # (at your option) any later version.
10
+ #
11
+ # Blifutils is distributed in the hope that it will be useful,
12
+ # but WITHOUT ANY WARRANTY; without even the implied warranty of
13
+ # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14
+ # GNU General Public License for more details.
15
+ #
16
+ # You should have received a copy of the GNU General Public License
17
+ # along with Blifutils. If not, see <http://www.gnu.org/licenses/>.
18
+
19
+
20
+ module BlifUtils
21
+
22
+ module AST
23
+
24
+ class TranslationUnit
25
+ attr_reader :modelList
26
+
27
+ def initialize (modList = [])
28
+ @modelList = modList
29
+ end
30
+
31
+ def pretty_print
32
+ ret = ''
33
+ @modelList.each {|model| ret += model.pretty_print(0)}
34
+ return ret
35
+ end
36
+ end # BlifUtils::AST::TranslationUnit
37
+
38
+
39
+ class Model
40
+ attr_reader :name, :header, :commands, :isBlackBox
41
+
42
+ def initialize (name, header, commands = [])
43
+ @name = name
44
+ @header = header
45
+ @commands = commands
46
+ @isBlackBox = not(@commands.index{|command| command.class == AST::BlackBox}.nil?)
47
+ if @isBlackBox and not(@commands.reject{|command| command.class == AST::BlackBox}.empty?) then
48
+ STDERR.puts "WARNING: Blackbox \"#{@name}\" contains non blackbox commands"
49
+ @commands = @commands.reject{|command| command.class == AST::BlackBox}.uniq
50
+ end
51
+ end
52
+
53
+ def pretty_print (indent)
54
+ str = ' '*indent + "#{@isBlackBox ? 'Black box' : 'Model'}:\n" + ' '*(indent+1) + "Name: \"#{@name}\"\n"
55
+ @header.each{|headEl| str += headEl.pretty_print(indent+1)}
56
+ @commands.each{|com| str += com.pretty_print(indent+1)} unless @isBlackBox
57
+ return str
58
+ end
59
+ end # BlifUtils::AST::Model
60
+
61
+
62
+ class ModelHeaderElementInputs
63
+ attr_reader :inputList
64
+
65
+ def initialize (inputList)
66
+ @inputList = inputList
67
+ end
68
+
69
+ def pretty_print (indent)
70
+ return ' '*indent + "Inputs: #{@inputList.collect{|str| "\"#{str}\""}.join(', ')}\n"
71
+ end
72
+ end # BlifUtils::AST::ModelHeaderElementInputs
73
+
74
+
75
+ class ModelHeaderElementOutputs
76
+ attr_reader :outputList
77
+
78
+ def initialize (outputList)
79
+ @outputList = outputList
80
+ end
81
+
82
+ def pretty_print (indent)
83
+ return ' '*indent + "Outputs: #{@outputList.collect{|str| "\"#{str}\""}.join(', ')}\n"
84
+ end
85
+ end # BlifUtils::AST::ModelHeaderElementOutputs
86
+
87
+
88
+ class ModelHeaderElementClock
89
+ attr_reader :clockList
90
+
91
+ def initialize (clockList)
92
+ @clockList = clockList
93
+ end
94
+
95
+ def pretty_print (indent)
96
+ return ' '*indent + "Clocks: #{@clockList.collect{|str| "\"#{str}\""}.join(', ')}\n"
97
+ end
98
+ end # BlifUtils::AST::ModelHeaderElementClock
99
+
100
+
101
+ class LogicGate
102
+ attr_reader :inputs, :output, :single_output_cover_list
103
+
104
+ def initialize (identifier_list, single_output_cover_list)
105
+ @inputs = identifier_list[0 ... -1]
106
+ @output = identifier_list[-1]
107
+ @single_output_cover_list = single_output_cover_list
108
+ end
109
+
110
+ def pretty_print (indent)
111
+ str = ' '*indent + "Logic gate:\n"
112
+ str += ' '*(indent+1) + "Inputs: #{@inputs.collect{|idf| "\"#{idf}\""}.join(', ')}\n"
113
+ str += ' '*(indent+1) + "Output: \"#{@output}\"\n"
114
+ str += ' '*(indent+1) + "Cover list:\n"
115
+ @single_output_cover_list.each do |inputs_output|
116
+ str += ' '*(indent+2) + "#{inputs_output[0].collect{|strbit| case strbit when 0 then '0' when 1 then '1' else '-' end}.join} | #{inputs_output[1]}\n"
117
+ end
118
+ return str
119
+ end
120
+ end # BlifUtils::AST::LogicGate
121
+
122
+
123
+ class GenericLatch
124
+ attr_reader :input, :output, :initValue, :ctrlType, :ctrlSig
125
+
126
+ def initialize (input, output, initValue: 3, ctrlType: :re, ctrlSig: nil)
127
+ @input = input
128
+ @output = output
129
+ @initValue = initValue
130
+ @ctrlType = ctrlType
131
+ @ctrlSig = ctrlSig
132
+ end
133
+
134
+ def pretty_print (indent)
135
+ str = ' '*indent + "Latch:\n"
136
+ str += ' '*(indent+1) + "Input: \"#{@input}\"\n"
137
+ str += ' '*(indent+1) + "Output: \"#{@output}\"\n"
138
+ str += ' '*(indent+1) + "Initial value: \"#{@initValue}\"\n"
139
+ str += ' '*(indent+1) + "Type: \"#{@ctrlType}\"\n"
140
+ str += ' '*(indent+1) + "Clock signal: #{@ctrlSig.nil? ? "nil" : "\"#{@ctrlSig}\""}\n"
141
+ return str
142
+ end
143
+ end # BlifUtils::AST::GenericLatch
144
+
145
+
146
+ class ModelReference
147
+ attr_reader :modelName, :formalAcutalList
148
+
149
+ def initialize (modelName, formalAcutalList)
150
+ @modelName = modelName
151
+ @formalAcutalList = formalAcutalList
152
+ end
153
+
154
+ def pretty_print (indent)
155
+ str = ' '*indent + "Model reference:\n"
156
+ str += ' '*(indent+1) + "Model name: \"#{@modelName}\"\n"
157
+ str += ' '*(indent+1) + "Formal / Actual mapping:\n"
158
+ @formalAcutalList.each do |form_act|
159
+ str += ' '*(indent+2) + "\"#{form_act[0]}\" -> \"#{form_act[1]}\"\n"
160
+ end
161
+ return str
162
+ end
163
+ end # BlifUtils::AST::ModelReference
164
+
165
+
166
+ class BlackBox; end # BlifUtils::AST::BlackBox
167
+
168
+
169
+ class SubfileReference
170
+ attr_reader :fileName
171
+
172
+ def initialize (fileName)
173
+ @fileName = fileName
174
+ end
175
+
176
+ def pretty_print (indent)
177
+ str = ' '*indent + "Sub file reference: \"#{@fileName}\"\n"
178
+ return str
179
+ end
180
+ end # BlifUtils::AST::SubfileReference
181
+
182
+ end # BlifUtils::AST
183
+
184
+ end # BlifUtils
185
+