Last active
December 31, 2015 07:39
-
-
Save tomoasleep/7955555 to your computer and use it in GitHub Desktop.
パイプラインの各ステージごとの命令デコーダを作るスクリプトを書いた。.vhd.erbたのしい!
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
require 'yaml' | |
require 'erb' | |
require 'forwardable' | |
class Hash | |
def except_keys_in(*keys) | |
hash_clone = self.clone | |
keys.each { |k| hash_clone.delete k } | |
hash_clone | |
end | |
end | |
class DecoderMaker | |
def initialize(yaml_path, stage_name) | |
@yaml = YAML.load(File.read(yaml_path)) | |
@stages = @yaml['has_state'].map { |stage| "#{stage}_state" } | |
@orders = @yaml['order'] | |
@dependencies = @yaml['dependencies'] | |
@stage_idx = @stages.find_index("#{stage_name}_state") | |
unless @stage_idx | |
raise "stage name'#{stage_name}_state' isnot exist in [#{@stages.join(', ')}]" | |
end | |
end | |
def run | |
parse_orders('result', @orders) | |
@order_groups = @order_groups_each_stage.transpose[@stage_idx] | |
@result_group = @order_groups.last | |
puts to_vhdl | |
end | |
private | |
def parse_orders(group_name, orders) | |
settings = orders['settings'] | |
order_type = "#{settings['type']}_type" | |
order_prefix = settings['prefix'] | |
_, order_state_maps = | |
orders | |
.except_keys_in('settings') | |
.reverse_each | |
.reduce( | |
[Array.new(@stages.size, 'nop'), {}] | |
) do |(last_s, os_maps), (order, v)| | |
states = case v | |
when Hash | |
parse_orders(order, v) | |
when Array | |
@stages.zip(v).map { |stage, state| "#{stage}_#{state}" } | |
when String | |
v | |
else | |
last_s | |
end | |
order_name = (order == 'others') ? order : "#{order_prefix}_#{order}" | |
[states, os_maps.merge(order_name => states)] | |
end | |
signals = @stages.map { |stage| "#{stage}_#{group_name}" } | |
signal_types = @stages.map { |stage| "#{stage}_type" } | |
@order_groups_each_stage ||= [] | |
@order_groups_each_stage << OrderGroup | |
.new_each_stage(signals, signal_types, order_state_maps, order_type) | |
signals | |
end | |
def to_vhdl | |
DecoderPresenter.new( | |
@order_groups, @result_group, @stages[@stage_idx], @dependencies).to_vhdl | |
end | |
end | |
class DecoderPresenter | |
TempletePath = File.expand_path('../templetes/decoder.vhd.erb', __FILE__) | |
attr_reader :dependencies | |
def initialize(order_groups, result_group, stage, dependencies) | |
@order_groups = order_groups | |
@result_group = result_group | |
@stage = stage | |
@dependencies = dependencies | |
end | |
def groups | |
@order_groups.map { |g| OrderGroupWrapper.new(g) } | |
end | |
def result_group | |
OrderGroupWrapper.new(@result_group) | |
end | |
def decoder_name | |
"#{@stage}_decoder" | |
end | |
def decoder_name | |
"#{@stage}_decoder" | |
end | |
def to_vhdl | |
file_content = File.read(TempletePath) | |
templete = ERB.new(file_content, nil, '-') | |
templete.result(binding) | |
end | |
end | |
class OrderGroup | |
def self.new_each_stage(signals, signal_types, order_state_maps, order_type) | |
order_state_maps = | |
order_state_maps | |
.values | |
.transpose.map { |v| Hash[order_state_maps.keys.zip(v)] } | |
[signals, signal_types, order_state_maps].transpose.map do |args| | |
new(*args, order_type) | |
end | |
end | |
attr_reader :signal, :signal_type, :order_state_map, :order_type | |
def initialize(signal, signal_type, order_state_map, order_type) | |
@signal = signal | |
@order_state_map = order_state_map | |
@signal_type = signal_type | |
@order_type = order_type | |
end | |
end | |
class OrderGroupWrapper | |
extend Forwardable | |
def_delegators :@order_group, | |
:signal, :signal_type, :order_type, :order_state_map | |
def initialize(order_group) | |
@order_group = order_group | |
end | |
def input_name | |
order_type.gsub(/_type$/, '') | |
end | |
def group_by_select | |
(tb = order_state_map.except_keys_in('others')) | |
.keys | |
.group_by { |k| tb[k] } | |
end | |
def others_value | |
order_state_map['others'] | |
end | |
end | |
DecoderMaker.new(ARGV[0], ARGV[1]).run |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
library ieee; | |
use ieee.std_logic_1164.all; | |
use ieee.numeric_std.all; | |
library work; | |
use work.const_opcode.all; | |
use work.typedef_opcode.all; | |
use work.const_pipeline_state.all; | |
entity exec_state_decoder is | |
port( | |
opcode: in opcode_type; | |
funct: in funct_type; | |
state: out exec_state_type | |
); | |
end exec_state_decoder; | |
architecture behave of exec_state_decoder is | |
signal exec_state_io: exec_state_type; | |
signal exec_state_f_group: exec_state_type; | |
signal exec_state_r_group: exec_state_type; | |
signal exec_state_result: exec_state_type; | |
begin | |
with funct select | |
exec_state_io <= | |
exec_state_nop when io_fun_oh | io_fun_ob | io_fun_ow | io_fun_ih | io_fun_ib | io_fun_iw, | |
exec_state_nop when others; | |
with funct select | |
exec_state_f_group <= | |
exec_state_fpu when f_fun_fsqrt | f_fun_finv | f_fun_fmul | f_fun_fadd, | |
exec_state_sub_fpu when others; | |
with funct select | |
exec_state_r_group <= | |
exec_state_jmpr when r_fun_jalr | r_fun_jr, | |
exec_state_alu_shift when r_fun_sra | r_fun_srl | r_fun_sll, | |
exec_state_alu when others; | |
with opcode select | |
exec_state_result <= | |
exec_state_jmp when i_op_jal | i_op_j, | |
exec_state_alu_imm when i_op_slti | i_op_addi, | |
exec_state_sub_fpu when i_op_fmvi, | |
exec_state_alu when i_op_imvf | i_op_bgez | i_op_bgtz | i_op_blez | i_op_bltz | i_op_bne | i_op_beq, | |
exec_state_nop when i_op_lwf | i_op_lw | i_op_swf | i_op_sw, | |
exec_state_io when i_op_io, | |
exec_state_f_group when i_op_f_group, | |
exec_state_r_group when i_op_r_group, | |
exec_state_alu_zimm when others; | |
state <= exec_state_result; | |
end behave; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
dependencies: | |
- const_opcode | |
- typedef_opcode | |
- const_pipeline_state | |
pipeline_stage: | |
- fetch | |
- decode | |
- execute | |
- memory | |
- write_back | |
has_state: | |
- exec | |
- mem | |
- write_back | |
order: | |
settings: | |
type: | |
opcode | |
prefix: | |
i_op | |
beq: | |
bne: | |
bltz: | |
blez: | |
bgtz: | |
bgez: | |
- alu | |
- branch | |
- nop | |
sw: | |
- nop | |
- sram_write | |
- nop | |
# TODO implement mem_fpu_write | |
swf: | |
- nop | |
- sram_write | |
- nop | |
lw: | |
- nop | |
- sram_read | |
- mem_wb | |
# TODO implement mem_fpu_wb | |
lwf: | |
- nop | |
- sram_read | |
- mem_wb | |
# TODO move r_group | |
imvf: | |
- alu | |
- nop | |
- fpu_wb | |
fmvi: | |
- sub_fpu | |
- nop | |
- alu_wb | |
addi: | |
slti: | |
- alu_imm | |
- nop | |
- alu_imm_wb | |
j: | |
- jmp | |
- nop | |
- nop | |
jal: | |
- jmp | |
- nop | |
- jal_wb | |
others: | |
- alu_zimm | |
- nop | |
- alu_imm_wb | |
r_group: | |
settings: | |
type: | |
funct | |
prefix: | |
r_fun | |
sll: | |
srl: | |
sra: | |
- alu_shift | |
- nop | |
- alu_wb | |
jr: | |
- jmpr | |
- nop | |
- nop | |
jalr: | |
- jmpr | |
- nop | |
- jal_wb | |
others: | |
- alu | |
- nop | |
- alu_wb | |
f_group: | |
settings: | |
type: | |
funct | |
prefix: | |
f_fun | |
fadd: | |
fmul: | |
finv: | |
fsqrt: | |
- fpu | |
- nop | |
- fpu_wb | |
others: | |
- sub_fpu | |
- nop | |
- fpu_wb | |
io: | |
settings: | |
type: | |
funct | |
prefix: | |
io_fun | |
iw: | |
- nop | |
- io_write_w | |
- io_wb | |
ib: | |
- nop | |
- io_write_b | |
- io_wb | |
ih: | |
- nop | |
- io_write_h | |
- io_wb | |
ow: | |
- nop | |
- io_read_w | |
- nop | |
ob: | |
- nop | |
- io_read_b | |
- nop | |
oh: | |
- nop | |
- io_read_h | |
- nop | |
others: | |
- nop | |
- nop | |
- nop |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
library ieee; | |
use ieee.std_logic_1164.all; | |
use ieee.numeric_std.all; | |
library work; | |
<%- dependencies.each do |dep| -%> | |
use work.<%= dep %>.all; | |
<%- end -%> | |
entity <%= decoder_name %> is | |
port( | |
opcode: in opcode_type; | |
funct: in funct_type; | |
state: out <%= result_group.signal_type %> | |
); | |
end <%= decoder_name %>; | |
architecture behave of <%= decoder_name %> is | |
<%- groups.each do |group| -%> | |
signal <%= group.signal %>: <%= group.signal_type %>; | |
<%- end -%> | |
begin | |
<%- groups.each do |group| %> | |
with <%= group.input_name %> select | |
<%= group.signal %> <= | |
<%- group.group_by_select.each do |state, orders| -%> | |
<%= state %> when <%= orders.join(' | ') %>, | |
<%- end -%> | |
<%= group.others_value %> when others; | |
<%- end %> | |
state <= <%= result_group.signal %>; | |
end behave; |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment