hipe_ultra_mod2.erl
来自「OTP是开放电信平台的简称」· ERL 代码 · 共 222 行
ERL
222 行
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% ULTRASPARC MACHINE MODEL%%%% This module is used by the scheduler.%% The following interface is used:%% ...%%%% NOTES:%% - the machine model is simple (on the verge of simplistic)%% * all FUs are pipelined => model only one cycle at a time%% * instruction latencies are mostly 1%% * floating point is left for later (I _think_ it works, but ...)%% - conservative: instructions that require multiple resources are%% modelled as 'single'; instead, they could reserve IEU+BR or whatever%% - possibly inefficient: I think machine state model could be turned into%% a bitvector.-module(hipe_ultra_mod2).-export([init_resources/1, init_instr_resources/2, resources_available/4, advance_cycle/1 ]).-export([raw_latency/2, war_latency/2, waw_latency/2, %% m_raw_latency/2, %% m_war_latency/2, %% m_waw_latency/2, m_raw_latency/0, m_war_latency/0, m_waw_latency/0, br_to_unsafe_latency/2, unsafe_to_br_latency/2, br_br_latency/2 ]).-include("../sparc/hipe_sparc.hrl").-define(debug(Str,Args),ok).%-define(debug(Str,Args),io:format(Str,Args)).-define(debug_ultra(Str,Args),ok).%-define(debug_ultra(Str,Args),io:format(Str,Args)).%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% Straightforward and somewhat simplistic model for UltraSparc:%% - only one cycle at a time is modelled%% - resources are simplified:%% * ieu0, ieu1, ieu, mem, br, single%% * per-cycle state = done | { I0, I1, NumI, X, Mem, Br }%% * unoptimized representation (could be bit vector)init_resources(_Size) -> ?debug_ultra('init res ~p~n',[_Size]), empty_state().%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%init_instr_resources(N,Nodes) -> ultra_instr_rsrcs(Nodes,hipe_vectors:new(N, '')).ultra_instr_rsrcs([],I_res) -> I_res;ultra_instr_rsrcs([N|Ns],I_res) -> ultra_instr_rsrcs(Ns,ultra_instr_type(N,I_res)).ultra_instr_type({N,I},I_res) -> hipe_vectors:set(I_res,N-1,instr_type(I)).instr_type(I) -> case I of #move{} -> ieu; #multimove{} -> %% TODO: expand multimoves before scheduling ieu; #alu{} -> case hipe_sparc:alu_operator(I) of '>>' -> ieu0; '<<' -> ieu0; _ -> ieu end; #alu_cc{} -> ieu1; #sethi{} -> ieu; #load{} -> mem; #store{} -> mem; #b{} -> br; #br{} -> br; #goto{} -> br; #jmp_link{} -> % imprecise; should be mem+br? single; #jmp{} -> % imprecise br; #call_link{} -> % imprecise; should be mem+br? single; #cmov_cc{} -> % imprecise single; #cmov_r{} -> % imprecise single; #load_atom{} -> % should be resolved to sethi/or single; #load_address{} -> % should be resolved to sethi/or single; #load_word_index{} -> % should be resolved to sethi/or single; %% uncommon types: #label{} -> none; #nop{} -> none; #comment{} -> none; _ -> exit({ultrasparc_instr_type,{cant_schedule,I}}) end.%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%resources_available(_Cycle, I, Rsrc, I_res) -> res_avail(instruction_resource(I_res, I), Rsrc).instruction_resource(I_res, I) -> hipe_vectors:get(I_res, I-1).%% The following function checks resource availability.%% * all function units are assumed to be fully pipelined, so only%% one cycle at a time is modelled.%% * for IEU0 and IEU1, these must precede all generic IEU instructions%% (handled by X bit)%% * at most 2 integer instructions can issue in a cycle%% * mem is straightforward%% * br closes the cycle (= returns done).%% * single requires an entirely empty state and closes the cycleres_avail(ieu0, { free, I1, NumI, free, Mem, Br }) when is_integer(NumI), NumI < 2 -> { yes, { occ, I1, NumI+1, free, Mem, Br }};res_avail(ieu1, { _I0, free, NumI, free, Mem, Br }) when is_integer(NumI), NumI < 2 -> { yes, { free, occ, NumI+1, free, Mem, Br }};res_avail(ieu, { I0, I1, NumI, _X, Mem, Br }) when is_integer(NumI), NumI < 2 -> { yes, { I0, I1, NumI+1, occ, Mem, Br }};res_avail(mem, { I0, I1, NumI, X, free, Br }) -> { yes, { I0, I1, NumI, X, occ, Br }};res_avail(br, { _I0, _I1, _NumI, _X, _Mem, free }) -> { yes, done };res_avail(single, { free, free, 0, free, free, free }) -> { yes, done };res_avail(_, _) -> no.%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%advance_cycle(_Rsrc) -> empty_state().empty_state() -> { free, free, 0, free, free, free }.%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% Latencies are taken from UltraSparc hardware manual%%%% *** UNFINISHED ***%% more precisely, they are taken from my memory of the US-manual%% at the moment.%%%% Note: all ld/st are assumed to hit in the L1 cache (D-cache),%% which is sort of imprecise.raw_latency(alu, store) -> 0;raw_latency(load, _) -> 2; % only if load is L1 hitraw_latency(alu_cc, b) -> 0;raw_latency(_I0, _I1) -> 1.war_latency(_I0, _I1) -> 0.waw_latency(_I0, _I1) -> 1.%% *** UNFINISHED ***%% At present, all load/stores are assumed to hit in the L1 cache,%% which isn't really satisfying.%% m_raw_latency(_St, _Ld) ->%% 1.%% %% m_war_latency(_Ld, _St) ->%% 1.%% %% m_waw_latency(_St1, _St2) ->%% 1.%% Use these for 'default latencies' = do not permit reordering.m_raw_latency() -> 1.m_war_latency() -> 1.m_waw_latency() -> 1.br_to_unsafe_latency(_BrTy, _UTy) -> 0.unsafe_to_br_latency(_UTy, _BrTy) -> 0.br_br_latency(_BrTy1, _BrTy2) -> 0.
⌨️ 快捷键说明
复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?