blifutils 0.0.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -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
+